#include "PlayerUI.h"
#include "PokerLogic.h"
#include "PokerPlayer.h"
#include "CardUI.h"
#include <algorithm>
#include <functional>

#define SHOW_VIRTUAL_PLAYER_CARD  0

PlayerUI::PlayerUI() : IDialog(), m_select_type(CARD_TYPE::ERROR_CARD)
{
    RegDialogCtrl("num_bg", num_bg);
    RegDialogCtrl("flag_lord", flag_lord);
    RegDialogCtrl("clock", clock);
    RegDialogCtrl("icon_head", icon_head);
    RegDialogCtrl("txt_count", txt_count);
    RegDialogCtrl("txt_tick", txt_tick);
    RegDialogCtrl("outArea", m_cradAreaOut);
    RegDialogCtrl("inArea", m_cradAreaHand);
}

PlayerUI::~PlayerUI(){
}

void PlayerUI::onUILoaded() {
    this->flag_lord->setVisible(false);
    this->num_bg->setVisible(false);
    this->clock->setVisible(false);
    this->m_skip = Sprite::createWithSpriteFrameName("buchu.png");
    this->m_skip->setVisible(false);
    this->m_rootNode->addChild(m_skip);
}

void PlayerUI::setPlayer(std::shared_ptr<PokerPlayer> player) {
    this->m_player = player;
    if (this->m_player != nullptr) {
        this->m_player->addActionListener([this](const PokerPlayer * const thePlayer, PLAYER_STATE state, int32_t card) {
            uint8_t seat = thePlayer->getSeat();
            m_state = state;
            if (state == PLAYER_STATE::ON_CARD_IN) {
                // 发牌
                this->flag_lord->setVisible(thePlayer->getCardCount() > 17);
                this->txt_count->setString(utility::toString(thePlayer->getCardCount()));
                this->num_bg->setVisible(true);
                if (seat == 0) {
                    this->refreshUI(thePlayer->getCardCount() <= 17);
                }
#if defined(SHOW_VIRTUAL_PLAYER_CARD) && (SHOW_VIRTUAL_PLAYER_CARD == 1)
                else if (seat == 1) {
                    CardUI* testUI = CardUI::create();
                    testUI->setData(card);
                    testUI->setLocalZOrder(thePlayer->getCardCount());
                    testUI->setPosition((thePlayer->getCardCount() - 17) * 50.0f, -120.0f);
                    testUI->setAnchorPoint(Vec2(0.5f, 1.0f));
                    m_cradAreaOut->addChild(testUI);
                } else if (seat == 2) {
                    CardUI* testUI = CardUI::create();
                    testUI->setData(card);
                    testUI->setLocalZOrder(thePlayer->getCardCount());
                    testUI->setPosition(thePlayer->getCardCount() * 50.0f, -120.0f);
                    testUI->setAnchorPoint(Vec2(0.5f, 1.0f));
                    m_cradAreaOut->addChild(testUI);
                }
#endif
            } else if (state == PLAYER_STATE::ON_CARD_OUT_START) {
                clock->setVisible(true);
                txt_tick->setString(utility::toString((int)PokerLogic::shard()->getCountdown()));
                // 清空出牌区域
                m_cradAreaOut->removeAllChildren();
            } else if (state == PLAYER_STATE::ON_CARD_OUT_OVER) {
                static std::vector< int32_t > data;
                data.clear();
                thePlayer->getLastOutCards(data);
                auto ui = m_player;
                if (data.empty()) {
                    // 不出
                    m_skip->setPosition((seat == 1 ? -200.0f : 200.0f), (seat == 0 ? 100.0f : -50.0f));
                    m_skip->setVisible(true);
                    m_skip->stopAllActions();
                    m_skip->setOpacity(255);
                    m_skip->runAction(Sequence::create(DelayTime::create(1.0f), FadeOut::create(1.0f), NULL));
                } else {
                    // 出牌
                    m_skip->setVisible(false);
                    // 刷新出牌区域
                    CardUI* postUI = nullptr;
                    uint8_t master = PokerLogic::shard()->getMasterSeat();
                    int cardCount = (int)data.size();
                    for (int i = 0; i < cardCount; ++i) {
                        postUI = CardUI::create();
                        postUI->setData(data[i]);
                        postUI->setLocalZOrder(i);
                        postUI->setPosition((seat == 1 ? ((i - cardCount + 1) * 50.0f) : (i * 50.0f)), -120.0f);
                        postUI->setAnchorPoint(Vec2(0.5f, 1.0f));
                        postUI->showFlag(master == seat);
                        m_cradAreaOut->addChild(postUI);
                    }
                }
                clock->setVisible(false);
                this->txt_count->setString(utility::toString(thePlayer->getCardCount()));
            } else if (state == PLAYER_STATE::ON_INFO_CHANGE) {
                this->clock->setVisible(false);
                this->m_skip->setVisible(false);
            }
        });
        Size visibleSize = Director::getInstance()->getVisibleSize();
        uint8_t seat = this->m_player->getSeat();
        //this->setPosition(visibleSize.width * 0.5f, visibleSize.height * 0.5f);
        if (seat == 0) {
            // 手牌展示区建立缓存, 最多20张牌, 直接丢20个UI
            for (int i = 1; i < 21; ++i) {
                CardUI* ui = CardUI::create();
                ui->setPosition(i * 55.0f, 10000.0f);
                ui->setLocalZOrder(i);
                ui->setAnchorPoint(Vec2(0.5f, 0.5f));
                this->m_cradAreaHand->addChild(ui);
                this->m_handCardUI.emplace_back(ui);
            }
            auto pos = this->m_cradAreaHand->getPosition();
            this->m_cradAreaOut->setPosition(pos.x + 200.0f, pos.y + 180.0f);
            this->addEventListener("ClickCardUI", callfuncO_selector(PlayerUI::onClickCardUI));
            //this->runAction(MoveTo::create(0.2f, Vec2(120, 120)));
            this->setPosition(120, 120);
            utility::setSpriteFrame(icon_head, "head/vtouxiang_10.png");
        } else if (seat == 1) {
            //this->runAction(MoveTo::create(0.2f, Vec2(visibleSize.width - 120, visibleSize.height - 80)));
            this->setPosition(visibleSize.width - 120, visibleSize.height - 80);
            utility::setSpriteFrame(icon_head, "head/vtouxiang_07.png");
        } else {
            //this->runAction(MoveTo::create(0.2f, Vec2(120, visibleSize.height - 80)));
            this->setPosition(120, visibleSize.height - 80);
            utility::setSpriteFrame(icon_head, "head/vtouxiang_06.png");
        }
        this->m_cradAreaHand->setScale(0.72f);
        this->m_cradAreaOut->setScale(0.5f);
    }
}

// 不换人再来一局, 清理UI
void PlayerUI::cleanUI() {
    this->flag_lord->setVisible(false);
    this->num_bg->setVisible(false);
    this->clock->setVisible(false);
    this->m_skip->setVisible(false);
    this->m_cradAreaOut->removeAllChildren();
    for (auto& ui : m_handCardUI) {
        if (ui != nullptr) {
            ui->setSelected(false);
            ui->setPositionY(10000.0f);
        }
    }
}

void PlayerUI::refreshUI(bool cardInMode) {
    if (this->m_cradAreaHand != nullptr && this->m_player != nullptr && this->m_player->getSeat() == 0) {
        std::vector< int32_t > arr;
        this->m_player->getHandCards(arr);
        size_t count = this->m_cradAreaHand->getChildrenCount();
        size_t i = 0;
        uint8_t master = PokerLogic::shard()->getMasterSeat();
        for ( ; i < arr.size(); ++i) {
            CardUI* ui = this->m_handCardUI[i];
            if (ui != nullptr) {
                ui->setData(arr[i], true);
                ui->setPositionY(-50.0f);
                ui->showFlag(master == m_player->getSeat() && !cardInMode);
                ui->setSelected(false);
            }
        }
        for (; i < count; ++i) {
            auto ui = this->m_handCardUI[i];
            if (ui) {
                ui->setPositionY(10000.0f);
            }
        }
    }
}

void PlayerUI::onEnter() {
    IDialog::onEnter();
    this->scheduleUpdate();
}

void PlayerUI::onExit() {
    this->unscheduleUpdate();
    IDialog::onExit();
}

void PlayerUI::update(float delta) {
    if (this->m_state == PLAYER_STATE::ON_CARD_OUT_START) {
        this->txt_tick->setString(utility::toString((int)PokerLogic::shard()->getCountdown()));
    }
}

bool PlayerUI::canPushCard() const {
    return this->m_select_type != CARD_TYPE::ERROR_CARD;
}

void PlayerUI::onClickCardUI(Ref* sender) {
    uint8_t mySeat = this->m_player->getSeat();
    uint8_t uActiveSeat = PokerLogic::shard()->getActiveSeat(); // 该谁出牌？
    CardUI* ui = dynamic_cast<CardUI*>(sender);
    if (ui != nullptr && ui->getParent() == this->m_cradAreaHand) {
        if (mySeat == uActiveSeat) {
            ui->setPositionY(ui->isSelected() ? 0.0f : -50.0f);
        } else {
            ui->setSelected(false);
            ui->setPositionY(-50.0f);
        }
    }
    SimpleAudioEngine::getInstance()->playEffect("sound/effect/click_cards.mp3");
    if ((mySeat == uActiveSeat) && PokerLogic::shard()->getGameRunning()) {
        // 判断牌型是否符合要求, 根据状态决定<出牌>按钮是否可以点击
        std::vector< int32_t > arr;
        if (this->m_cradAreaHand != nullptr) {
            CardUI* ui = nullptr;
            int count = this->m_player->getCardCount();
            for (int i = 0; i < count; ++i) {
                ui = this->m_handCardUI[i];
                if (ui != nullptr && ui->isSelected()) {
                    arr.emplace_back(ui->getCard());
                }
            }
        }
        // 获取到状态
        CARDS_DATA tryCardsData = PokerLogic::CheckCardType(arr);
        // 拉到上家出的牌
        std::vector< int32_t > cardsLastOut;
        uint8_t seat = PokerLogic::shard()->getRealSeat(mySeat, -1);
        PokerLogic::shard()->getPlayer(seat)->getLastOutCards(cardsLastOut);
        if (cardsLastOut.empty()) {
            // 上家没出? 再找上上家看看
            seat = PokerLogic::shard()->getRealSeat(mySeat, -2);
            PokerLogic::shard()->getPlayer(seat)->getLastOutCards(cardsLastOut);
        }
        if (cardsLastOut.empty()) {
            // 斗地主,3个人参与,此时前两家都没出牌,那就随便出喽
            this->m_select_type = tryCardsData._type;
        } else if(cardsLastOut.size() == arr.size() || tryCardsData._type == BOMB_CARD || tryCardsData._type == MISSILE_CARD) {
            CARDS_DATA preCardsData = PokerLogic::CheckCardType(cardsLastOut);
            // 根据别人的牌,选自己的出牌方式,必须能大过对方
            if ((tryCardsData._type == MISSILE_CARD) ||
                // 相同牌型
                (tryCardsData._type == preCardsData._type && tryCardsData._cards[0] > preCardsData._cards[0]) ||
                // 不同牌型用炸弹或火箭
                (tryCardsData._type != preCardsData._type
                 && preCardsData._type != MISSILE_CARD
                 && (tryCardsData._type == BOMB_CARD || tryCardsData._type == MISSILE_CARD)
                 && (preCardsData._type != BOMB_CARD || tryCardsData._cards[0] > preCardsData._cards[0]))) {
                this->m_select_type = tryCardsData._type;
            } else {
                this->m_select_type = ERROR_CARD;
            }
        } else {
            this->m_select_type = ERROR_CARD;
        }
        // 通知主UI
        this->m_ntfMgr->postNotification("CheckUserOutCardType", this);
    }
}

void PlayerUI::resetCardSelect() {
    int count = this->m_player->getCardCount();
    for (ssize_t i = 0; i < count; ++i) {
        CardUI* ui = this->m_handCardUI[i];
        if (ui != nullptr) {
            ui->setPositionY(-50.0f);
            ui->setSelected(false);
        }
    }
    this->m_cradAreaOut->removeAllChildren();
}

bool PlayerUI::tipCardSelect() {
    // 出牌提示
    this->resetCardSelect();
    // 查询
    std::vector< int32_t > data;
    this->m_player->tryOutputCard(data, true);
    // 刷新UI
    if (data.empty()) {
        // 没有能大过对方的, 直接不出
        this->m_player->doCardOut(data);
        return false;
    } else {
        int count = this->m_player->getCardCount();
        CardUI* ui = nullptr;
        for (size_t j = 0; j < data.size(); j++) {
            for (int i = 0; i < count; ++i) {
                ui = this->m_handCardUI[i];
                if (ui != nullptr && !ui->isSelected() && ui->getCard() == data[j]) {
                    ui->setPositionY(0.0f);
                    ui->setSelected(true);
                }
            }
        }
        // 获取到状态, 通知主UI
        CARDS_DATA tryCardsData = PokerLogic::CheckCardType(data);
        this->m_select_type = tryCardsData._type;
        this->m_ntfMgr->postNotification("CheckUserOutCardType", this);
        return true;
    }
}

void PlayerUI::cardOut() {
    std::vector< int32_t > arr;
    if (this->m_cradAreaHand != nullptr) {
        CardUI* ui = nullptr;
        std::vector< int32_t > handCards;
        this->m_player->getHandCards(handCards);
        int count = this->m_player->getCardCount();
        for (int i = 0; i < count; ++i) {
            ui = this->m_handCardUI[i];
            if (ui != nullptr && ui->isSelected()) {
                arr.emplace_back(ui->getCard());
                assert(handCards[i] == ui->getCard());
            }
        }
    }
    this->m_player->doCardOut(arr);
    this->refreshUI(false);
}

